<?php

namespace App\Http\Requests\Reservation;

use App\Models\Reservation\Schedule;
use Carbon\Carbon;
use Illuminate\Database\Query\Builder;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;

class ReservationStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     * @return array
     */
    public function rules()
    {
        return [
            'hospital_id' => 'required|integer|exists:tn_scene,id',
            'patient_id'  => 'required|integer|exists:tn_user_base,id',
            'doctor_id'   => [
                'required', 'integer',
                Rule::exists('tn_user_base', 'id')->where(
                    function (Builder $query) {
                        $query->where('hospital_id', $this->input('hospital_id'));
                    }
                ),
            ],
            'time'        => 'required|date_format:Y-m-d|after:today',
            'am'          => 'required|boolean',
            'section'     => 'required',
            'purpose'     => 'string|max:255',
            'remark'      => 'string|max:255',
        ];
    }

    public function messages()
    {
        return [
            'hospital_id.required' => '预约医院 不能为空！',
            'hospital_id.integer'  => '预约医院 的标识必须是一个数字。',
            'hospital_id.exists'   => '选择的 预约医院 不存在。',
            'patient_id.required'  => '',
            'patient_id.integer'   => '',
            'patient_id.exists'    => '',
            'doctor_id.required'   => '预约医生 不能为空！',
            'doctor_id.integer'    => '预约医生 的标识必须是一个数字。',
            'doctor_id.exists'     => '选择的 预约医生 不存在。',
            'time.required'        => '预约日期 不能为空！',
            'time.date_format'     => '预约日期 格式错误。',
            'am.required'          => '时间段 不能为空！',
            'am.boolean'           => '时间段 格式错误。',
            'section.required'     => '时间 不能为空！',
            'section.in'           => '选择的时间 超出范围。',
            'room.required'        => '诊室号 不能为空！',
            'room.integer'         => '诊室号 标识错误。',

            'purpose.max' => '预约内容 最大 :max 个字符',
            'remark.max'  => '备注 最大 :max 个字符',
        ];
    }

    public function withValidator(Validator $validator)
    {
        $validator->after(function (Validator $validator) {
            if ($validator->messages()->isEmpty()) {

                $input = $this->input();
                list($start, $end) = explode('-', $input['section']);
                if (!is_numeric($start) || !is_numeric($end)) {
                    $validator->messages()->add('section', '时间段格式错误。');
                    return false;
                }

                if ($start >= $end) {
                    $validator->messages()->add('section', '开始时间要小于结束时间。');
                    return false;
                }

                $schedule = Schedule::where(
                    [
                        'doctor_id' => $input['doctor_id'],
                        'time'      => $input['time'],
                    ])->first();

                if (is_null($schedule)) {
                    $validator->messages()->add('doctor_or_time', '该医生这个时间段没有预约安排。');
                    return false;
                }

                $validator->addRules(['room' => 'required|integer|size:' . $schedule->room]);

                $result = collect($schedule->toArray()['workload'])->map(function ($item) {
                    return collect($item)->pluck('end', 'start')->toArray();
                });

                $set = [$start => $end];

                $result = $result->filter(function ($item) use ($set) {
                    return array_intersect_assoc($set, $item);
                });

                if (!$result->count()) {
                    $validator->messages()->add('section', '该医生这个时间段没有预约安排。');
                }
            }
        });
    }
}
